<template>
	<view class="online-report-form">
		<online-filter-box class="filter-box" :supportSort="false" @reset="onReset" v-if="show">
			<!-- 过滤字段 -->
			<online-custom-block subWidgetClass="filter-item" :widgetList="filterWidgetList" />
		</online-filter-box>
		<view class="main-box">
			<u-form ref="form" :label-width="(formConfig.labelWidth || 100) + 'px'"
				:label-position="formConfig.labelPosition || 'left'">
				<online-custom-block :widgetList="chartWidgetList" />
			</u-form>
		</view>
		<!-- 弹出子表单 -->
		<u-popup v-model="showSubPage" mode="left" length="100%">
			<online-report-form :pageId="subPageId" :params="subPageParams" @close="onCloseSubPage" />
		</u-popup>
	</view>
</template>

<script>
	import {
		formatDate,
		findItemFromList,
		findTreeNode,
		setObjectToSessionStorage
	} from '@/utils';
	import {
		getAllWidgetList,
		isChart
	} from './utils.js';
	import { ReportDatasetController, ReportOperationController, ReportDictController, ReportPageController } from '@/api/reportController.js';
	import { DictionaryController } from '@/api';

	export default {
		data() {
			return {
				show:false,
				isReady: false,
				formData: {},
				datasetMap: new Map(),
				dictMap: new Map(),
				showSubPage: false,
				subPageId: undefined,
				subPageParams: undefined,
			}
		},
		props: {
			formConfig: {
				type: Object
			},
			height: {
				type: String
			},
			// 是否表单编辑模式
			isEdit: {
				type: Boolean
			},
			// 当前选中组件
			currentWidget: {
				type: Object
			},
			fullscreen: {
				type: Boolean
			},
			// 表单参数
			params: {
				type: String
			},
			mode: {
				type: String,
				default: 'mobile'
			}
		},
		provide() {
			return {
				form: () => {
					return {
						...this.formConfig,
						mode: this.mode,
						isEdit: this.isEdit,
						formType: this.SysOnlineFormType.REPORT,
						readOnly: false,
						getWidgetValue: this.getWidgetValue,
						getWidgetVisible: this.getWidgetVisible,
						onValueChange: this.onValueChange,
						onWidgetValueChange: this.onWidgetValueChange,
						getDictDataList: this.getDictDataList,
						getQueryParam: this.getQueryParam,
						listDataWithGroup: this.listDataWithGroup,
						listDictData: this.listDictData,
						listColumnData: this.listColumnData,
						loadDatasetInfo: this.loadDatasetInfo,
						getDropdownParams: this.getDropdownParams,
						onChartDblClick: this.onChartDblClick,
						isActive: (widget) => {
							return this.currentWidget === widget;
						}
					}
				}
			}
		},
		onPullDownRefresh(){
			setTimeout(function(){
				uni.stopPullDownRefresh()
			},1000)
		},
		methods: {
			onBack() {
				uni.navigateBack();
			},
			onCloseSubPage(refresh) {
				this.showSubPage = false;
			},
			onReset() {
				if (Array.isArray(this.filterWidgetList)) {
					this.filterWidgetList.forEach(widget => {
						this.onValueChange(widget, undefined);
					});
				}
			},
			onInput(widgetList) {
				this.formConfig.widgetList = widgetList;
			},
			onWidgetClick(widget) {
				this.$emit('widgetClick', widget);
			},
			initFormWidget(widget) {
				if (widget == null) return;
				if (widget.props && widget.props.dictInfo) {
					let dict = this.dictMap.get(widget.props.dictInfo.dictId);
					widget.props.dictInfo.dict = dict;
					this.show = true
				}
				if (widget.eventInfo == null) {
					widget.eventInfo = {};
				}
				if (Array.isArray(widget.childWidgetList)) {
					widget.childWidgetList = widget.childWidgetList.map(subWidget => {
						return this.initFormWidget(subWidget);
					});
				}
				if (widget && widget.props && widget.props.datasetInfo && widget.props.datasetInfo.datasetId) {
					let dataset = this.datasetMap.get(widget.props.datasetInfo.datasetId);
					return {
						...widget,
						dataset: dataset,
						columnList: (dataset || {}).columnList
					}
				} else {
					return {
						...widget
					}
				}
			},
			initFormData() {
				return new Promise((resolve, reject) => {
					this.getAllWidget.forEach(widget => {
						this.$set(this.formData, widget.variableName, undefined);
					});
					this.loadAllDataset(this.formConfig.widgetList).then(res => {
						return this.loadReportDictList();
					}).then(res => {

						this.formConfig.widgetList = this.formConfig.widgetList.map(widget => {
							return this.initFormWidget(widget);
						});
						this.initPageWatch();
						resolve();
					}).catch(e => {
						console.log(e);
						reject(e);
					});
				});
			},
			buildWatch(widget, filter) {
				if (filter.filterValueType === this.FilterValueKind.FORM_PARAM) {
					// 报表参数
					this.$watch('formParams.' + filter.paramValue, () => {
						if (widget.widgetImpl) widget.widgetImpl.refresh();
					});
				} else if (filter.filterValueType === this.FilterValueKind.WIDGET_DATA) {
					// 过滤组件
					let filterWidget = findItemFromList(this.getAllWidget, filter.formWidgetId, 'widgetId');
					if (filterWidget != null) {
						this.$watch('formData.' + filterWidget.variableName, () => {
							if (widget.widgetImpl) widget.widgetImpl.refresh();
						});
					}
				}
			},
			buildDropdownWatch(widget) {
				if (widget && Array.isArray((widget.props.dictInfo || {}).paramList)) {
					widget.props.dictInfo.paramList.forEach(param => {
						if (param.dictValueType === this.SysOnlineParamValueType.TABLE_COLUMN && param.dictValue !=
							null) {
							let filterWidget = findItemFromList(this.getAllWidget, param.dictValue, 'widgetId');
							if (filterWidget != null) {
								this.$watch('formData.' + filterWidget.variableName, () => {
									this.formData[widget.variableName] = undefined;
									if (widget && widget.widgetImpl && typeof widget.widgetImpl.reset ===
										'function') {
										widget.widgetImpl.reset();
									}
								});
							}
						}
					});
				}
			},
			initPageWatch() {
				this.getAllWidget.forEach(widget => {
					if (isChart(widget.widgetType) && widget.props.datasetInfo) {
						// 组件过滤
						if (Array.isArray(widget.props.datasetInfo.filterList)) {
							widget.props.datasetInfo.filterList.forEach(filter => {
								this.buildWatch(widget, filter);
							});
						}
						// 数据集过滤
						if (Array.isArray(widget.props.datasetInfo.datasetFilterParams)) {
							widget.props.datasetInfo.datasetFilterParams.forEach(filter => {
								this.buildWatch(widget, filter);
							});
						}
						// 指标过滤
						if (Array.isArray(widget.props.datasetInfo.valueColumnList)) {
							widget.props.datasetInfo.valueColumnList.forEach(valueColumn => {
								if (valueColumn && Array.isArray(valueColumn.filterList)) {
									valueColumn.filterList.forEach(filter => {
										this.buildWatch(widget, filter);
									});
								}
							});
						}
					}
					// 下拉数据过滤
					this.buildDropdownWatch(widget);
				});
			},
			loadDataset(datasetId) {
				const self = this
				return new Promise((resolve, reject) => {
					let params = {
						datasetId: datasetId
					}
					
					ReportDatasetController.view(this, params).then(res => {
						try {
							let info = JSON.parse(res.datasetInfo);
							res.datasetParamList = info.paramList;
						} catch (e) {
							res.datasetParamList = [];
						}
						self.datasetMap.set(datasetId, res);
						resolve(res);
					}).catch(e => {
						reject(e);
					});
				});
			},
			getAllDatasetIdsByWidgetList(widgetList, datasetIdList = []) {
				if (Array.isArray(widgetList)) {
					widgetList.forEach(widget => {
						if (widget && widget.props && widget.props.datasetInfo && widget.props.datasetInfo
							.datasetId) {
							if (widget.props.datasetInfo.datasetId && datasetIdList.indexOf(widget.props.datasetInfo.datasetId) === -1) {
								datasetIdList.push(widget.props.datasetInfo.datasetId);
							}
						}
						this.getAllDatasetIdsByWidgetList(widget.childWidgetList, datasetIdList);
					});
				}
			},
			loadAllDataset(widgetList) {
				let datasetIdList = [];
				this.getAllDatasetIdsByWidgetList(widgetList, datasetIdList);
				console.log('DDDD', datasetIdList)
				return Promise.all(datasetIdList.map(datasetId => {
					return this.loadDataset(datasetId);
				}));
			},
			loadReportDictList() {
				this.dictMap = new Map();
				return new Promise((resolve, reject) => {
					DictionaryController.dictReportDict(this, {}).then(res => {
						res.forEach(item => {
							item.dictData = item.dictDataJson ? JSON.parse(item.dictDataJson) : undefined;
							this.dictMap.set(item.id, item);
						});
						resolve();
					}).catch(e => {
						reject(e);
					});
				});
			},
			getSystemVariableValue(systemVariableType) {
				switch (systemVariableType) {
					case this.OnlineSystemVariableType.CURRENT_USER:
						return this.getUserInfo.showName;
					case this.OnlineSystemVariableType.CURRENT_DEPT:
						return this.getUserInfo.deptName;
					case this.OnlineSystemVariableType.CURRENT_DATE:
						return formatDate(new Date(), 'YYYY-MM-DD');
					case this.OnlineSystemVariableType.CURRENT_TIME:
						return formatDate(new Date(), 'YYYY-MM-DD HH:mm:ss');
					case this.OnlineSystemVariableType.FLOW_CREATE_USER:
						return (this.flowInfo || {}).processInstanceInitiator || this.getUserInfo.showName;
				}
				return undefined;
			},
			getWidgetValue(widget) {
				return this.formData[widget.variableName];
			},
			getWidgetVisible(widget) {
				if (widget == null || widget.eventInfo == null) return true;
				if (typeof widget.eventInfo[this.OnlineFormEventType.VISIBLE] === 'function') {
					return widget.eventInfo[this.OnlineFormEventType.VISIBLE]();
				} else {
					return true;
				}
			},
			onValueChange(widget, value) {
				this.formData[widget.variableName] = value;
			},
			onWidgetValueChange(widget, value, dictData) {
				if (widget == null || widget.eventInfo == null) return;
				let fun = this.getScriptFunction(widget.eventInfo, this.OnlineFormEventType.CHANGE);
				fun && fun(value);
			},
			getDictDataList(dictInfo, params) {
				if (dictInfo == null || dictInfo.dictId == null) return Promise.resolve([]);
				return this.listDictData(dictInfo.dictId, params);
			},
			getScriptFunction(eventInfo, eventType) {
				if (eventInfo && typeof eventInfo[eventType] === 'function') {
					return eventInfo[eventType];
				} else {
					return null;
				}
			},
			getParamValue(valueType, valueData) {
				switch (valueType) {
					case this.SysOnlineParamValueType.TABLE_COLUMN: {
						let widget = findItemFromList(this.getAllWidget, valueData, 'widgetId');
						return widget ? this.formData[widget.variableName] : undefined;
					}
					case this.SysOnlineParamValueType.STATIC_DICT:
						return Array.isArray(valueData) ? valueData[1] : undefined;
					case this.SysOnlineParamValueType.INPUT_VALUE:
						return valueData;
				}
			},
			getDropdownParams(widget) {
				if (Array.isArray(widget.props.dictInfo.paramList)) {
					let params = {};
					for (let i = 0; i < widget.props.dictInfo.paramList.length; i++) {
						let dictParam = widget.props.dictInfo.paramList[i];
						if (dictParam.dictValue == null || dictParam.dictValueType == null) continue;
						let widgetData = this.getParamValue(dictParam.dictValueType, dictParam.dictValue);
						if (widgetData == null) return null;
						params[dictParam.dictParamName] = widgetData;
					}
					return params;
				} else {
					return {};
				}
			},
			getQueryParam(filter) {
				if (filter.filterValueType === this.FilterValueKind.FORM_PARAM) {
					let formParam = this.formParams[filter.paramValue];
					if (formParam != null) {
						if (formParam.filterValueType === this.FilterValueKind.INNER_VARIABLE) {
							// 内置变量参数
							return {
								...filter,
								filterValueType: this.FilterValueKind.INNER_VARIABLE,
								paramValue: formParam
							}
						} else {
							return {
								...filter,
								paramValue: formParam
							}
						}
					} else {
						return {
							...filter,
							paramValue: undefined
						}
					}
				} else if (filter.filterValueType === this.FilterValueKind.WIDGET_DATA) {
					let filterWidget = findItemFromList(this.getAllWidget, filter.formWidgetId, 'widgetId');
					let paramValue, dateRange;
					if (filterWidget != null) {
						paramValue = this.formData[filterWidget.variableName];
						if (filterWidget.widgetType === this.ReportWidgetType.Cascader) {
							if (Array.isArray(paramValue)) {
								paramValue = paramValue[paramValue.length - 1];
							} else {
								paramValue = undefined;
							}
						}
						if (paramValue === '') paramValue = undefined;
						if (filterWidget.widgetType === this.ReportWidgetType.DateRange || filterWidget.widgetType === this
							.ReportWidgetType.Date) {
							switch (filterWidget.props.type) {
								case 'daterange':
									dateRange = 'date';
									break;
								case 'monthrange':
									dateRange = 'month';
									break;
								case 'datetimerange':
								case 'datetime':
									dateRange = undefined;
									break;
								default:
									dateRange = filterWidget.props.type;
							}
						}
					}
					return {
						...filter,
						dateRange,
						paramValue
					}
				} else {
					return {
						...filter
					}
				}
			},
			listDataWithGroup(params) {
				return new Promise((resolve, reject) => {
					let finalParams = {
						...params,
						pageCode: this.formConfig.pageCode
					}
					let httpCall = this.isEdit ?
						ReportOperationController.previewDataWithGroup(this, finalParams) : ReportOperationController.listDataWithGroup(this, finalParams);
					httpCall.then(res => {
						resolve(res);
					}).catch(e => {
						reject(e);
						console.log(e);
					});
				});
			},
			listDictData(dictId, params) {
				if (params == null) {
					return Promise.reject();
				}
				let filterDtoList = Object.keys(params).map(key => {
					return {
						columnName: key,
						columnValue: params[key]
					}
				});
				return new Promise((resolve, reject) => {
					ReportDictController.listDictData(this, {
						dictId: dictId,
						filterDtoList
					}).then(res => {
						resolve(res);
					}).catch(e => {
						reject(e);
					});
				});
			},
			listColumnData(datasetId, columnId) {
				return new Promise((resolve, reject) => {
					ReportDatasetController.listDataWithColumn(this, {
						datasetId: datasetId,
						columnId: columnId
					}).then(res => {
						resolve(res);
					}).catch(e => {
						reject(e);
					});
				});
			},
			loadDatasetInfo(datasetId) {
				return new Promise((resolve, reject) => {
					let params = {
						datasetId: datasetId
					}
					ReportDatasetController.view(this, params).then(res => {
						try {
							let info = JSON.parse(res.datasetInfo);
							res.datasetParamList = info.paramList;
							res.columnList = info.columnList || res.columnList;
						} catch (e) {
							res.datasetParamList = [];
						}
						resolve(res);
					}).catch(e => {
						reject(e);
					});
				});
			},
			gotoPage(pageId, params) {
				this.showSubPage = true;
				this.subPageId = pageId;
				this.subPageParams = JSON.stringify(params || {});
			},
			gotoRouter(routerName, routerParams) {
				// TODO 跳转
				let menuItem = findTreeNode(this.getMenuList, routerName, 'formRouterName');
				if (menuItem != null) {
					// 查找要跳转的是不是菜单，如果是执行菜单选中操作
					this.setCurrentMenuId(menuItem.menuId);
				} else {
					// 如果跳转的路由不是菜单，跳转过去
					this.$router.push({
						name: routerName,
						query: routerParams.query,
						param: routerParams.param
					});
				}
			},
			onChartDblClick(widget, data) {
				if (widget != null && Array.isArray(widget.operationList)) {
					// 下钻事件
					let drillOperation = findItemFromList(widget.operationList, this.SysCustomWidgetOperationType.DRILL,
						'type');
					if (drillOperation != null && drillOperation.enabled) {
						let pageId = drillOperation.pageId;
						let filterList = drillOperation.filterList;
						let params = {};
						if (Array.isArray(filterList)) {
							let dataset = this.datasetMap.get(widget.props.datasetInfo.datasetId);
							params = filterList.reduce((retObj, item) => {
								if (item.filterValueType === this.FilterValueKind.DRILL_DATA && dataset) {
									if (widget.props && widget.props.datasetInfo) {
										let columnId = item.paramValue;
										let column = findItemFromList(dataset.columnList, columnId, 'columnId');
										// 维度字段
										if (Array.isArray(widget.props.datasetInfo.categroyColumnList)) {
											let category = findItemFromList(widget.props.datasetInfo
												.categroyColumnList, columnId, 'columnId');
											if (category != null) {
												retObj[item.paramName] = data[column.columnName];
											}
										}
										// 指标字段
									}
								} else {
									retObj[item.paramName] = this.getQueryParam(item);
								}
								return retObj;
							}, {});
						}
						this.gotoPage(pageId, params);
						return;
					}
					// 路由跳转操作
					let routeOperation = findItemFromList(widget.operationList, this.SysCustomWidgetOperationType.ROUTE,
						'type');
					if (routeOperation != null && !this.isEdit && routeOperation.enabled) {
						let queryParams = (routeOperation.routeParams || []).reduce((retObj, item) => {
							if (item.valueType === 'fixed') {
								// 固定值
								retObj[item.paramName] = item.paramValue;
							} else if (item.valueType === 'bind') {
								// 绑定到字段
								let columnName;
								if (widget.dataset) {
									let column = findItemFromList(widget.dataset.columnList, item.paramValue,
										'columnId');
									if (widget.dataset.datasetType === this.DatasetType.API) {
										columnName = [];
										do {
											columnName.push(column.columnName);
											column = findItemFromList(widget.dataset.columnList, column.parentId,
												'columnId');
										} while (column == null);
										columnName = columnName.reverse();
									} else {
										columnName = (column || {}).columnName;
									}
								}
								let value = this.getDataString(columnName, data);
								if (value) retObj[item.paramName] = value;
							}
							return retObj;
						}, {});
						this.gotoRouter(
							routeOperation.routeName, {
								query: queryParams
							})
					}
				}
			},
			// 根据配置的字段取字符串数据
			getDataString(columnName, data) {
				if (Array.isArray(columnName)) {
					let dataValue = columnName.length > 0 ? data : undefined;

					for (let i = 0; i < columnName.length; i++) {
						let name = columnName[i];
						if (name == null || dataValue == null) {
							dataValue = undefined;
							break;
						}
						dataValue = dataValue[name];
					}
					return dataValue;
				} else {
					return data[columnName];
				}
			},
		},
		computed: {
			filterWidgetTypeList() {
				return [
					this.SysCustomWidgetType.MobileInputFilter,
					this.SysCustomWidgetType.MobileRadioFilter,
					this.SysCustomWidgetType.MobileCheckBoxFilter,
					this.SysCustomWidgetType.MobileSwitchFilter,
					this.SysCustomWidgetType.MobileDateRangeFilter,
					this.SysCustomWidgetType.MobileNumberRangeFilter
				];
			},
			getAllWidget() {
				if (Array.isArray(this.formConfig.widgetList)) {
					return getAllWidgetList(this.formConfig.widgetList);
				}
				return [];
			},
			formParams() {
				let params = {};
				try {
					if (this.params) params = JSON.parse(this.params);
				} catch (e) {
					console.log(e);
				}
				return params;
			},
			filterWidgetList() {
				let that = this
				console.log(this.getAllWidget, 'getAllWidget')
				let  res = this.getAllWidget.filter(widget => {
					return that.filterWidgetTypeList.indexOf(widget.widgetType) !== -1;
				})
				console.log(res, 'filterWidgetList')
				// console.log(this.filterWidgetTypeList)
				return res
			},
			chartWidgetList() {
				return this.getAllWidget.filter(widget => {
					return this.filterWidgetTypeList.indexOf(widget.widgetType) === -1;
				});
			}
		},
		watch: {
			'formConfig': {
				handler() {
					if (this.formConfig == null) return;
					this.isReady = false;
					this.datasetMap = new Map();
					this.initFormData().then(res => {
						this.isReady = true;
					}).catch(e => {
						uni.showToast({
							icon: 'error',
							title: '页面初始化失败！',
							success() {
								uni.navigateBack();
							}
						});
					});
				},
				immediate: true
			}
		}
	}
</script>

<style scoped lang="less">
	.online-report-form {
		height: 100vh;
		background: #F6F7F9;
		position: relative;
		z-index: 1;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: flex-start;

		.filter-box {
			background: #ffffff;
			padding: 0px 36rpx;
			position: fixed;
			left: 0;
			right: 0;
			flex-shrink: 0;
			z-index: 99999;
		}

		.main-box {
			flex: 1;
			overflow: auto;
			padding: 32rpx;
			position: absolute;
			top: 80rpx;
			width: 100%;
		}
	}
</style>
<style>
  .filter-item + .filter-item {
    margin-top: 10px;
  }
</style>